-- BishopM
-- Created by panyl
-- 主教模块

module("BishopM", package.seeall);

local bishops = {};
local bishopSkills = {};

local whenLeaveDungeon;
local startFloor;
local whenNextFloor;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    bishops = {};
    bishopSkills = {};

    -- 转换下bishop信息表
    local bishop_CSV = get_bishop_CSV();
    for i = 1, #bishop_CSV do
        bishops[bishop_CSV[i].class_id] = bishop_CSV[i];
    end

    bishop_CSV = {};

    -- bishop_skill表
    local bishop_skill_CSV = get_bishop_skill_CSV();
    for i = 1, #bishop_skill_CSV do
        local row = bishop_skill_CSV[i];
        bishopSkills[row.skill_id] = row;

        -- 技能整理
        bishops[row.class_id]["skills"] = bishops[row.class_id]["skills"] or {};

        table.insert(bishops[row.class_id]["skills"], row.skill_id);
    end

    bishop_skill_CSV = {};
end

function init()
    loadCsv();

    -- 移除所有
    EventMgr.removeAll("BishopM");

    -- 关注进入下一层地牢事件
    EventMgr.register("BishopM", event.NEXT_FLOOR, whenNextFloor);

    -- 关注离开地牢事件
    EventMgr.register("BishopM", event.LEAVE_DUNGEON, whenLeaveDungeon);

    -- 关注层数回退（大地之门等技能）的事件
    EventMgr.register("BishopM", event.BACK_FLOOR, function()
        whenBackFloor();
    end);

    -- 开始新回合
    CombatM.registerEndRoundCB("bishop_attack", attack);

    -- 开始打包验证客户端结果
    EventMgr.register("BishopM", event.START_PACK_VERIFY_RESULT, function(para)
        syncBishopData();
    end);

    DungeonServiceM.registerStartDungeonCB("bishop", startFloor);

    -- 进入夹层
    EventMgr.register("BishopM", event.ENTER_UNREAL_DUNGEON, whenEnterUnreal);
end

-- 进入夹层
function whenEnterUnreal()
    if not ME.user.bishop then
        return;
    end

    -- 删除上次行动的回合
    ME.user.bishop.action = 1;
    ME.user.bishop.skill_round = 0;

    -- 同步一下
    syncBishopData();
end

-- 进入下一层
function whenNextFloor()
    -- 先同步一下
    syncBishopData();

    local info = ME.user.dbase:query("bishop");
    if type(info) ~= "table" or type(info.class_id) ~= "number" then
        return;
    end

    -- 旧对象干掉
    ME.user.bishop = nil;

    -- 创建主教对象
    local bishop = createBishop(info.class_id, info);
    if not bishop then
        return;
    end

    -- 删除上次行动的回合
    bishop.action = 1;
    bishop.skill_round = 0;

    if bishop:isDead() then
        syncBishopData();
        return;
    end

    -- 自动增加5%+20的生命,10魔法，暂时固定
    local hp = math.modf(bishop:getHp() + bishop:getMaxHp() * 5 / 100 + 20);
    local mp = math.modf(bishop:getMp() + 10);

    hp = math.min(hp, bishop:getMaxHp());
    mp = math.min(mp, bishop:getMaxMp());

    bishop:setHp(hp);
    bishop:setMp(mp);

    syncBishopData();
end

-- 离开地牢，直接丢弃主教数据
whenLeaveDungeon = function()
    ME.user.bishop = nil;
    ME.user.dbase:delete("bishop");
    ME.user.dbase:delete("bishop_attrib");

    -- 删除主教技能给玩家的属性加成
    ME.user.dbase:delete("bishop_addon");
end

-- 开始新一层地牢
startFloor = function()
    -- 同步一次属性
    syncBishopData();

    local info = ME.user.dbase:query("bishop");

    if type(info) ~= "table" or type(info.class_id) ~= "number" then
        startFloorBishopPreTrans();
        return;
    end

    -- 旧对象不用了
    ME.user.bishop = nil;

    createBishop(info.class_id, info);

    startFloorBishopTrans();
end

-- 回退楼层
function whenBackFloor()
    -- 先同步一下
    syncBishopData();

    local info = ME.user.dbase:query("bishop");

    if type(info) ~= "table" or type(info.class_id) ~= "number" then
        return;
    end

    -- 旧对象不用了
    ME.user.bishop = nil;

    local bishop = createBishop(info.class_id, info);
    if bishop then
        bishop.action = 1;
        bishop.skill_round = 0;
    end

    syncBishopData();
end

-- 检索
function query(classId, path)
    local m = bishops[classId];

    if not m or not path then
        return m;
    end

    return m[path];
end

-- 检索主教技能
function querySkill(skillId, path)
    local m = bishopSkills[skillId];

    if not m or not path then
        return m;
    end

    return m[path];
end

-- 获取主教位置
function getBishopPos()
    local pos = 0;
    for index = 1, GRID_SIZE do
        local grid = DungeonM.getGridByPos(index);
        if grid.type == GRID_TYPE_BISHOP then
            pos = grid:getPos();
            break;
        end
    end

    return pos;
end

-- 初始化主教
function initBishopData()
    local ret = { };

    -- 如果玩家当前没有主教数据，花园就是空的
    local bishopInfo = ME.user.dbase:query("bishop");
    local bishop = ME.user.bishop;
    if bishop or bishopInfo and bishopInfo.class_id then
        local classId;
        if bishop then
            classId = bishop.classId;
        else
            classId = bishopInfo.class_id;
        end
        ret = {
            ["class_id"]     = classId,
        };
    end

    return ret;
end

-- 消耗
function doCost(cost)
    for key, amount in pairs(cost) do
        if type(key) == "number" then
            ItemM.costAmount(ME.user, key, amount);
        elseif type(key) == "string" then
            ME.user:costAttrib(key, amount);
        end
    end
end

-- 创建一个主教
function createBishop(classId, info)
    info = info or {};

    local dbase = table.add({
        ["class_id"] = classId,
        ["level"]  = info["level"] or 1,
        ["skills"] = {},
    }, info);

    if type(dbase["hp"]) ~= "number" then
        dbase["hp"] = FormulaM.invoke("BISHOP_BASE_HP");
    end

    if type(dbase["mp"]) ~= "number" then
        dbase["mp"] = FormulaM.invoke("BISHOP_BASE_MP");
    end

    local bishop = Bishop.new(classId, dbase);
    ME.user.bishop = bishop;

    bishop.action = info["action"] or CombatM.getRound();
    bishop.skill_round = info["skill_round"] or CombatM.getRound();

    PropM.refresh(bishop);

    return bishop;
end

-- 判断能否升级主教技能
function canUpgradeSkill(skillId)
    local bishop = ME.user.bishop;

    if not bishop then
        --trace("BishopM", "玩家当前没有主教。");
        return false;
    end

    -- 如果主教已经死亡了
    if bishop:isDead() then
        --trace("BishopM", "主教已经死亡了，不能升级");
        return "bishop_dead";
    end

    if not bishop:ownSkill(skillId) then
        --trace("BishopM", "主教%s当前没有技能%d，不能升级。", bishop:getName(), skillId);
        return false;
    end

    local baseSkill = SkillM.findBaseSkill(skillId);
    local maxLevel = querySkill(baseSkill, "max_level");
    if type(maxLevel) == "number" and bishop:getSkillLevel(skillId) >= maxLevel then
        trace("BishopM", "主教%s的技能%s已经达到最高等级",
            bishop:getName(), SkillM.query(baseSkill, "name"));
        return false;
    end

    -- 消耗
    local cost = FormulaM.invoke("CALC_UPGRADE_BISHOP_SKILL_COST", skillId);
    if type(cost) ~= 'table' then
        error("主教技能(%d)升级消耗配置有误", skillId);
    end

    local ok = true;
    for classId, amount in pairs(cost) do
        if type(classId) == "number" then
            ok = ItemM.getAmount(ME.user, classId) >= amount;
        elseif type(classId) == "string" then
            ok = ME.user.dbase:query(classId, 0) >= amount;
        end

        if true ~= ok then
            return "cost_lack";
        end
    end

    return ok;
end

-- 升级技能
function upgradeBishopSkill(skillId)
    -- 先判断下
    if true ~= canUpgradeSkill(skillId) then
        return false;
    end

    -- 先做消耗
    local cost = FormulaM.invoke("CALC_UPGRADE_BISHOP_SKILL_COST", skillId);
    doCost(cost);

    local bishop = ME.user.bishop;
    bishop:upgradeSkill(skillId);

    DungeonLogM.addLog(string.format("主教升级技能%d。", skillId));

    -- 刷新下属性
    PropM.refresh(bishop);

    -- 抛出事件
    EventMgr.fire(event.BISHOP_SKILL_UPGRADE, { ["skillId"] = skillId, });

    return true;
end

-- 能否升级
function canLevelUp()
    return false;
end

-- 主教升级
function levelUp()
    return false;
end

-- 判断能否恢复
function canCure(pos)
    local bishop = ME.user.bishop;
    if not bishop then
        trace("BishopM", "玩家没有主教");
        return false;
    end

    -- 如果主教已经死亡了
    if bishop:isDead() then
        trace("BishopM", "主教已经死亡了，不能恢复");
        return "bishop_dead";
    end

    local grid = DungeonM.getGridByPos(pos);
    if grid.type ~= GRID_TYPE_BREAD_MILL or
        grid.state == GRID_STATE_DISABLE then
        trace("BishopM", "格子不是面包磨坊，不能恢复");
        return false;
    end

    -- 判断消耗
    local ok = true;
    local cost = FormulaM.invoke("CALC_BISHOP_COST", "cure", bishop.classId);
    for classId, amount in pairs(cost) do
        if type(classId) == "number" then
            ok = ItemM.getAmount(ME.user, classId) >= amount;
        elseif type(classId) == "string" then
            ok = ME.user.dbase:query(classId, 0) >= amount;
        end

        if true ~= ok then
            return "cost_lack";
        end
    end

    return ok;
end

-- 治疗主教
function cureBishop(pos)
    -- 判断下
    if true ~= canCure(pos) then
        return false;
    end

    local bishop = ME.user.bishop;
    local cost = FormulaM.invoke("CALC_BISHOP_COST", "cure", bishop.classId);
    doCost(cost);

    local oriHp = bishop:getHp();
    local oriMp = bishop:getMp();

    -- 暂时简陋一点 TODO
    local recover = FormulaM.invoke("CALC_BISHOP_CURE_RECOVER");
    local hp = bishop:getHp() + recover["hp"];
    local mp = bishop:getMp() + recover["mp"];

    hp = math.min(hp, bishop:getMaxHp());
    mp = math.min(mp, bishop:getMaxMp());

    bishop:setHp(hp);
    bishop:setMp(mp);

    local recoverHp = hp - oriHp;
    local recoverMp = mp - oriMp;

    DungeonLogM.addLog(string.format("主教hp恢复%d，mp恢复%d。", recover["hp"], recover["mp"]));

    -- 同步一次数据
    syncBishopData();

    local grid = DungeonM.getGridByPos(pos);
    grid:changeState(GRID_STATE_DISABLE);

    -- 恢复参数
    local addList = {{"max_hp", recoverHp}, {"max_mp", recoverMp}};

    -- 抛出事件
    EventMgr.fire(event.CURE_BISHOP, {["pos"] = pos, ["add_list"] = addList});
    return true;
end

-- 判断能否复活
function canRevive()
    local bishop = ME.user.bishop;
    if not bishop then
        trace("BishopM", "玩家没有主教，不能复活。");
        return false;
    end

    -- 主教没死亡
    if not bishop:isDead() then
        trace("BishopM", "主教没死亡。");
        return false;
    end

    -- 消耗
    local ok = true;
    local cost = FormulaM.invoke("CALC_BISHOP_COST", "revive", bishop.classId);
    for classId, amount in pairs(cost) do
        if type(classId) == "number" then
            ok = ItemM.getAmount(ME.user, classId) >= amount;
        elseif type(classId) == "string" then
            ok = ME.user.dbase:query(classId, 0) >= amount;
        end

        if true ~= ok then
            return "cost_lack";
        end
    end

    return ok;
end

-- 复活主教
function reviveBishop()
    -- 判断下
    if true ~= canRevive() then
        return false;
    end

    local bishop = ME.user.bishop;
    local cost = FormulaM.invoke("CALC_BISHOP_COST", "revive", bishop.classId);
    doCost(cost);

    -- 复活
    local hp = math.modf(bishop:getMaxHp());
    local mp = math.modf(bishop:getMaxMp());

    bishop:revive(hp, mp);

    DungeonLogM.addLog(string.format("主教复活hp=%d，mp=%d", bishop:queryAttrib("hp"), bishop:queryAttrib("mp")));

    -- 同步一次数据
    syncBishopData();

    -- 抛出事件
    EventMgr.fire(event.BISHOP_REVIVE);
    return true;
end

-- 计算施放技能消耗
function calcSkillCost(skillId)
    -- 魔法值
    local baseSkill = SkillM.findBaseSkill(skillId);
    return querySkill(baseSkill, "require");
end

-- 是否满足技能倒计时
function skillCdAllow(skillId)
    local bishop = ME.user.bishop;

    -- 回合数判断
    local skillRound = bishop.skill_round or 0;
    local round = CombatM.getRound();
    local skillCd = querySkill(skillId, "skill_cd");

    local prefix = "formula_";
    -- 如果配置了公式，则调用公式计算
    if type(skillCd) == "string" and string.startWith(skillCd, "formula_") then
        local formulaName = string.sub(skillCd, string.len(prefix) + 1);
        skillCd = FormulaM.invoke(formulaName, ME.user, skillId, bishop:getSkillLevel(skillId));
    end

    if type(skillCd) == "number" and skillRound + skillCd > round then
        return false;
    end

    return true;
end

-- 是否满足MP值
function skillMpAllow(skillId)
    local bishop = ME.user.bishop;
    -- 魔法值
    local mp = calcSkillCost(skillId);
    if bishop:getMp() < mp then
        return false;
    end

    return true;
end

-- 判断能否使用技能
function canUseSkill(skillId, pos)
    local bishop = ME.user.bishop;
    if not bishop or bishop:isDead() then
        trace("BishopM", "没有主教或者主教已经死亡。");
        return false;
    end

    -- 主教是否拥有此技能
    if not bishop:ownSkill(skillId) then
        trace("BishopM", "主教没有技能%s。", SkillM.query(skillId, "name"));
        return false;
    end

    -- 魔法值
    local mp = calcSkillCost(skillId);
    if bishop:getMp() < mp then
        trace("BishopM", "主教魔法值不足，当前：%d，需求：%d。", bishop:getMp(), mp);
        return false;
    end

    -- 回合数判断
    if not skillCdAllow(skillId) then
        trace("BishopM", "上次在第%d回合施放技能，当前%d回合，不能释放", skillRound, round);
        return false;
    end

    -- 是否有效目标
    local grid = DungeonM.getGridByPos(pos);
    local monster = grid.monster;

    if not grid:isMonster() or not monster or monster:isDead() then
        trace("BishopM", "目标%d不是存活的怪物。", pos);
        return false;
    end

    return true;
end

-- 使用技能
function useSkill(skillId, pos)
    -- 判断
    if true ~= canUseSkill(skillId, pos) then
        return false;
    end

    local bishop = ME.user.bishop;
    local grid = DungeonM.getGridByPos(pos);
    local monster = grid.monster;

    -- 消耗魔法值
    local mp = calcSkillCost(skillId);
    bishop:setMp(bishop:getMp() - mp);

    local msg = string.format("主教使用技能，消耗魔法值：%d，当前魔法值：%d，最大魔法值：%d。", mp, bishop:getMp(), bishop:getMaxMp());
    DungeonLogM.addLog(msg);

    -- 施放技能
    local assailantInfo = {
        ["source"] = bishop,
        ["skill_id"] = skillId,
    };
    SkillM.apply(bishop, monster, skillId, CombatM.getRound(), { assailantInfo = assailantInfo });

    -- 一个回合事件
    EventMgr.fire(event.COMBAT_ROUND, pos);

    ME.user.bishop.skill_round = CombatM.getRound();
    syncBishopData();

    EventMgr.fire(event.BISHOP_USE_SKILL, {["pos"] = pos});

    return true;
end

-- 判断能否学习技能
function canLearnSkill(skillId)
    local bishop = ME.user.bishop;
    if not bishop then
        --trace("BishopM", "没有主教，不能学习主教技能。");
        return false;
    end

    -- 如果主教已经死亡了
    if bishop:isDead() then
        --trace("BishopM", "主教已经死亡了，不能升级");
        return "bishop_dead";
    end

    local skills = query(bishop.classId, "skills");
    if table.indexOf(skills, skillId) <= 0 then
        --trace("BishopM", "主教不能学习此技能。");
        return false;
    end

    if bishop:ownSkill(skillId) then
        --trace("BishopM", "主教已经拥有此技能。");
        return false;
    end

    -- 消耗
    local ok = true;
    local cost = FormulaM.invoke("CALC_UPGRADE_BISHOP_SKILL_COST", skillId);
    for classId, amount in pairs(cost) do
        if type(classId) == "number" then
            ok = ItemM.getAmount(ME.user, classId) >= amount;
        elseif type(classId) == "string" then
            ok = ME.user.dbase:query(classId, 0) >= amount;
        end

        if true ~= ok then
            return "cost_lack";
        end
    end

    return ok;
end

-- 学习技能
function learnSkill(skillId)
    if true ~= canLearnSkill(skillId) then
        return false;
    end

    local cost = FormulaM.invoke("CALC_UPGRADE_BISHOP_SKILL_COST", skillId);
    doCost(cost);

    local bishop = ME.user.bishop;
    bishop:learnSkill(skillId);

    -- 同步一次数据
    syncBishopData();

    -- 刷新下属性
    PropM.refresh(bishop);

    -- 抛出事件
    EventMgr.fire(event.BISHOP_SKILL_UPGRADE, { ["skillId"] = skillId, });
    return true;
end

-- 获取自动攻击轮次倒计时
function getAttackCountDown()
    local bishop = ME.user.bishop;
    if not bishop or bishop:isDead() then
        return nil;
    end

    local round = CombatM.getRound();
    local actionRound = bishop.action or 0;

    local cycle = query(bishop.classId, "cycle");
    if not cycle or cycle <= 0 then
        return;
    end

    return cycle - (round - actionRound) % cycle;
end

-- 主教自动攻击
function attack(para)
    if type(para) == "table" and para.not_move then
        return;
    end

    -- 随机选择目标攻击
    local bishop = ME.user.bishop;
    if not bishop then
        -- trace("BishopM", "没有主教对象。");
        return false;
    end

    -- 主教已经死亡了
    if bishop:isDead() then
        --trace("BishopM", "主教已经死亡了，不能攻击。");
        return false;
    end

    local round = CombatM.getRound();
    local actionRound = bishop.action or 0;

    if (actionRound >= round) then
        --trace("BishopM", "上次行动回合:%d，当前回合:%d", actionRound, round);
        return false;
    end

    local cycle = query(bishop.classId, "cycle");
    if type(cycle) ~= "number" or cycle <= 0 then
        --trace("BishopM", "主教 %d 不能攻击。", bishop.classId);
        return false;
    end

    if (round - actionRound) % cycle ~= 0 then
        --trace("BishopM", "当回合不能攻击，round = %d，action = %d", round, actionRound);
        return false;
    end

    -- 如果当前没有主教格子（比如是在各种副本中）
    if getBishopPos() <= 0 then
        --trace("BishopM", "当前副本没有主教。");
        return false;
    end

    bishop.action = round;

    -- 玩家死亡了
    if ME.user:isDead() then
        --trace("BishopM", "玩家死亡了，主教不能攻击");
        return false;
    end

    -- 随机选取一个目标
    local grids = {};
    for pos = 1, GRID_SIZE do
        local grid = DungeonM.getGridByPos(pos);
        if grid:isOpened() and grid:isMonster() and
            not grid.monster:isAudience() and not grid.monster:isDead() then
            table.insert(grids, grid);
        end
    end

    if #grids > 0 then
        -- 随机一个
        local rand = DungeonM.getRandSeed("bishop_attack") % #grids;
        local grid = grids[rand + 1];

        local pos = grid:getPos();
        if SkillM.canPhysic(bishop, grid.monster) then
            -- 攻击
            bishopAttack(pos);
        end
    end
end

-- 主教攻击
function bishopAttack(pos)
    local bishop = ME.user.bishop;
    if not bishop then
        -- trace("BishopM", "没有主教对象。");
        return false;
    end

    local grid = DungeonM.getGridByPos(pos);
    local round = CombatM.getRound();

    if not pos or pos <= 0 then
        return;
    else
        DungeonLogM.addLog(string.format("[BishopM]主教攻击目标%d，当前第%d回合。", grid:getPos(), round));

        -- 物理攻击
        if true == SkillM.physic(bishop, grid.monster, true) then
            -- 抛出主教攻击事件
            EventMgr.fire(event.BISHOP_ATTACK, { ["pos"] = pos, });
        end
    end
end

-- 获取主教主动技能
function getInitiativeSkill()
    local bishop = ME.user.bishop;
    local skills = query(bishop.classId, "skills");
    if skills == nil then
        return nil;
    end

    for _, skillId in pairs(skills) do
        if querySkill(skillId, "active") == 1 then
            return skillId;
        end
    end

    return nil;
end

-- 转换一次
function startFloorBishopTrans()
    if not ME.user.bishop then
        -- 没有主教
        return;
    end

    if getBishopPos() > 0 then
        -- 已经有格子了
        return;
    end

    -- 用召唤兽的就好
    local pos = SummonM.findSummonPos();
    if ActivityDungeonM.isInActivityBossLayer() then
        -- BOSS层固定位置
        local classId = ME.user.bishop.classId;
        local appointPos = query(classId, "boss_layer_pos") + 1; -- 客户端下标+1
        if type(appointPos) == "number" then
            pos = appointPos;
        end
    end

    if pos <= 0 then
        trace("BishopM", "没有空格，不出现主教格子");
        return;
    end

    bishopTrans(pos);
end

-- 换换格子
function bishopTrans(pos, classId)
    if not classId then
        classId = ME.user.bishop.classId;
    end

    local dungeonId = DungeonM.getDungeonId();
    local class = DungeonM.getClassByType(GRID_TYPE_BISHOP);
    local dbase = {
         ["dungeon_id"] = dungeonId,
         ["layer"] = DungeonM.currentLayer(),
         ["pos"] = pos,
         ["class"] = class,
         ["type"] = DungeonM.query(class, "type"),
         ["element"] = query(classId, "element")[dungeonId],
    };
    DungeonM.transformGrid(class, pos, GRID_STATE_OPEN, dbase);
end

-- 能否召唤
function canCall(pos)
    if ME.user.bishop then
        trace("BishopM", "玩家已经拥有主教");
        return false;
    end

    local grid = DungeonM.getGridByPos(pos);
    if grid.type ~= GRID_TYPE_BISHOP_PRE or
        grid.state == GRID_STATE_DISABLE then
        trace("BishopM", "格子：%d不是主教格子，不能召唤", pos);
        return false;
    end

    return true;
end

-- 召唤主教
function callBishop(pos)
    if true ~= canCall(pos) then
        return false;
    end

    -- 格子
    local grid = DungeonM.getGridByPos(pos);
    -- 召唤的主教
    local classId = grid.bishop_id;

    -- 设置失效
    grid:changeState(GRID_STATE_DISABLE);

    local monsterPets = query(classId, "monster_pets") or {};
    local activePet = ME.user.dbase:query("active_pet", 0);
    if table.indexOf(monsterPets, activePet) >= 0 then
        -- 白棋主教，变成怪物
        DungeonM.transGridToMonster(pos, grid.monster_element);
    else
        bishopTrans(pos, classId);

        createBishop(classId, {["class_id"] = classId});

        -- 初始携带技能
        initSkill();
    end

    EventMgr.fire(event.COMBAT_ROUND, pos);
end

-- 召唤主教的时候初始赠送技能
function initSkill()
    local bishop = ME.user.bishop;

    if not bishop then
        return;
    end

    local classId = bishop.classId;
    local initSkills = query(classId, "init_skill") or {};

    for skillId, level in pairs(initSkills) do
        repeat
            if level <= 0 then
                break;
            end

            if bishop:ownSkill(skillId) then
                -- 赠送的技能有了？？
                break;
            end

            for i = 1, level do
                if i == 1 then
                    bishop:learnSkill(skillId);
                else
                    bishop:upgradeSkill(skillId);
                end
            end

        until true;
    end

    -- 同步一次数据
    syncBishopData();

    -- 刷新下属性
    PropM.refresh(bishop);
end

-- 同步下数据到dbase下
function syncBishopData()
    local bishop = ME.user.bishop;
    if bishop then
        ME.user.dbase:set("bishop", bishop:getSaveData());
        return;
    end
end

-- 消耗的物品
function getCostItem(skillId)
    local itemId;
    local cost = FormulaM.invoke("CALC_UPGRADE_BISHOP_SKILL_COST", skillId);
    for classId, amount in pairs(cost) do
        return classId;
    end
    return 0;
end

-- 计算施放技能消耗
function calcSkillCost(skillId)
    -- 魔法值
    return querySkill(skillId, "require");
end

-- 获取主教预备位置
function getBishopPrePos()
    local pos = 0;
    for index = 1, GRID_SIZE do
        local grid = DungeonM.getGridByPos(index);
        if grid.type == GRID_TYPE_BISHOP_PRE then
            pos = grid:getPos();
            break;
        end
    end

    return pos;
end

-- 转换一次预备格子
function startFloorBishopPreTrans()
    if ME.user.bishop then
        -- 有主教
        return;
    end

    if ActivityDungeonM.isInActivityBossLayer() then
        -- BOSS层不出现
        return;
    end

    if getBishopPrePos() > 0 then
        -- 已经有格子了
        return;
    end

    bishopPreTrans();
end

-- 转换成预备格子
function bishopPreTrans()
    local dungeonId = DungeonM.getDungeonId();
    local class = DungeonM.getClassByType(GRID_TYPE_BISHOP_PRE);
    local elements = (DungeonM.getElementsByDungeon(dungeonId) or {})[class];
    if not elements then
        -- 没有元素集合
        return;
    end

    local element = elements[1]["id"];

    if not element then
        -- 没有元素
        return;
    end

    local dbase = DungeonM.queryElement(element, "dbase") or {};
    local bishopId = tonumber(dbase["bishop_id"]);
    local monsterPets = query(bishopId, "monster_pets") or {};
    local activePet = ME.user.dbase:query("active_pet", 0);
    if table.indexOf(monsterPets, activePet) >= 0 then
        -- 白棋主教，那就算了
        return;
    end

    -- 用召唤兽的就好
    local pos = SummonM.findSummonPos();
    if pos <= 0 then
        trace("BishopM", "没有空格，不出现主教预备格子");
        return;
    end

    dbase = {
         ["dungeon_id"] = dungeonId,
         ["layer"] = DungeonM.currentLayer(),
         ["pos"] = pos,
         ["class"] = class,
         ["type"] = DungeonM.query(class, "type"),
         ["element"] = element,
    };
    DungeonM.transformGrid(class, pos, GRID_STATE_OPEN, dbase);
end
